VK Cup 2016 - Round 1 E. Bear and Contribution(贪心)

题意:

$N,K\le 2\times 10^5,给定N个数,现在要使其中至少K个数变得相同$
$b,c\le 1000,其中增加5的代价是b,增加1的代价是c$

分析:

$显然的想法是都变成已有某个数比较优$
$但是b,c大小没给定,如果b很小,那么我们可以稍微通过+1变大我们这个数,同时其他的数+5$
$所以我们发现选择的数应该是a_i+j, j\in[0,5)$
$这样我们只要维护5个set,来动态维护k个数就好了$
$但是每次我们要O(1)计算出变成当前数的花费,其实只要把之前的数都变成[0,4)$
$之后再统一变成当前数就好辣,就可以O(1)计算了,注意负数哦$
$时间复杂度O(5nlogn)$

代码:

//
//  Created by TaoSama on 2016-03-30
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

typedef long long LL;
int n, k, a[N];
LL b, c;

int get(int x) {return (x % 5 + 5) % 5;}
int count(int x) {return (x - get(x)) / 5;}

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    scanf("%d%d%I64d%I64d", &n, &k, &b, &c);
    for(int i = 1; i <= n; ++i) scanf("%d", a + i);
    b = min(b, 5 * c);
    sort(a + 1, a + 1 + n);

    multiset<LL> s[5];
    LL ans = 1e18, cost[5] = {};

    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j < 5; ++j) {
            int wh = get(a[i] + j);
            int times = count(a[i] + j);
            LL cur = j * c - times * b;

            s[wh].insert(cur);
            cost[wh] += cur;
            if(s[wh].size() > k) {
                cost[wh] -= *s[wh].rbegin();
                s[wh].erase(s[wh].find(*s[wh].rbegin()));
            }

            if(s[wh].size() == k) {
                LL tmp = cost[wh] + times * b * k;
                ans = min(ans, tmp);
            }
        }
    }
    printf("%I64d\n", ans);
    return 0;
}